//
//  SocketConnectionManager.swift
//  Progress
//
//  Created by bin hu on 2025/6/30.
//

import Network
import SocketIO

// MARK: - Socket 连接管理
class SocketConnectionManager:NSObject {
    static let shared = SocketConnectionManager()
    
    private var manager: SocketManager?
    private var socket: SocketIOClient?
    private var retryAttempt = 0
    private var isConnected = false
    private var eventListeners = [String: [(Any) -> Void]]()
    
    private let queue = DispatchQueue(label: "com.socket.domainSwitch")
    private var currentDomainIndex = 0
    private let monitor = NWPathMonitor()
    private var timer = GCDTimer()
    
    // 连接状态回调
    var connectionStatusChanged: ((Bool) -> Void)?
    
    private override init() {
        super.init()
        addNotifications()
        setupNetworkMonitor()
    }
    
    func addNotifications() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(appDidEnterBackground),
            name: UIApplication.didEnterBackgroundNotification,
            object: nil
        )
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(appWillEnterForeground),
            name: UIApplication.willEnterForegroundNotification,
            object: nil
        )
    }
    
    // 网络状态监控
    private func setupNetworkMonitor() {
        monitor.pathUpdateHandler = { [weak self] path in
            guard let self else { return }
            if path.status == .satisfied {
                connect()
            }
        }
        monitor.start(queue: queue)
    }
    
    deinit {
        monitor.cancel()
        NotificationCenter.default.removeObserver(self)
    }
    
}

extension SocketConnectionManager {
    
    /// 建立连接
    func connect() {
        guard !isConnected else { return }
        
        let domains = DynamicDomainManager.shared.getSocketDomains()
        guard !domains.isEmpty else {
            DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
                self.connect()
            }
            return
        }
        
        attemptConnection(domains: domains, index: currentDomainIndex)
    }
    
    /// 断开连接
    func disconnect() {
        socket?.removeAllHandlers()
        socket?.disconnect()
        manager = nil
        socket = nil
        isConnected = false
        connectionStatusChanged?(false)
    }
    
    private func attemptConnection(domains: [String], index: Int) {
        queue.async {
            guard index < domains.count else {
                self.handleAllConnectionsFailed(domains: domains)
                return
            }
            
            let domain = domains[index]
            guard let url = URL(string: domain/*"wss://\(domain)"*/) else {
                self.attemptConnection(domains: domains, index: index + 1)
                return
            }
            
            log("\(url),\(self.currentDomainIndex)")
            self.disconnect() // 确保先断开现有连接
            
            let config: SocketIOClientConfiguration = [
                .log(false),
                .reconnects(false),
                .forceWebsockets(true),// 强制使用纯WebSocket协议
                .secure(false),  // 明确禁用SSL
                .connectParams(["EIO": "3",
                                "deviceId": UIDevice.current.identifierForVendor?.uuidString ?? ""])  // 指定Engine.IO协议版本
//                .secure(true),
//                .selfSigned(true),  // 允许自签名证书
//                .security(SSLSecurity(usePublicKeys: true))  // 使用项目中的
            ]
            
            self.manager = SocketManager(socketURL: url, config: config)
            self.socket = self.manager?.defaultSocket
            
            self.setupEventHandlers()
            
            // 开始连接
            self.socket?.connect()
        }
    }
    
    /// 注册事件监听
    private func setupEventHandlers() {
        
        socket?.on(clientEvent: .connect) { [weak self] _, _ in
            log("连接已建立")
            self?.handleConnectionSuccess()
        }
        
        socket?.on(clientEvent: .disconnect) { [weak self] _, _ in
            self?.handleDisconnect()
        }
        
        socket?.on(clientEvent: .error) { [weak self] data, _ in
            self?.handleConnectionError(data: data)
        }
        
        // 注册自定义事件监听
        for (event, handlers) in eventListeners {
            socket?.on(event) { [weak self] data, _ in
                self?.handleEvent(event, data: data)
            }
        }
    }
    
    /// 连接成功
    private func handleConnectionSuccess() {
        log("Socket 连接成功")
        isConnected = true
        retryAttempt = 0
        connectionStatusChanged?(true)
        
        // 标记域名健康
        if let host = socket?.manager?.socketURL.host {
            DynamicDomainManager.shared.markDomainHealthy("https://\(host)")
        }
        
        // 连接成功开启心跳
        startHeartTimer()
    }
    
    /// 失败连接处理
    private func handleDisconnect() {
        log("Socket 已断开")
        isConnected = false
        connectionStatusChanged?(false)
        attemptReconnect()
    }
    
    /// 连接错误
    private func handleConnectionError(data: [Any]) {
        log("Socket connection error: \(data)")
        isConnected = false
        connectionStatusChanged?(false)
        
        // 标记域名不健康
        if let host = socket?.manager?.socketURL.host {
            DynamicDomainManager.shared.markDomainUnhealthy("https://\(host)")
        }
        
        let domains = DynamicDomainManager.shared.getSocketDomains()
        if currentDomainIndex < (domains.count - 1) {
            currentDomainIndex += 1
        }else{
            currentDomainIndex = 0
        }
        
        attemptReconnect()
    }
    
    /// 重连
    private func attemptReconnect() {
        let delay = min(pow(2.0, Double(retryAttempt)), 20.0)
        retryAttempt += 1
        
        DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in
            self?.connect()
        }
    }
    
    /// All socket domains failed
    private func handleAllConnectionsFailed(domains: [String]) {
        print("All socket domains failed: \(domains)")
        
        // 通知用户
        NotificationCenter.default.post(
            name: Notification.Name("SocketConnectionFailed"),
            object: nil
        )
        
        // 15分钟后重试
        DispatchQueue.main.asyncAfter(deadline: .now() + 900) { [weak self] in
            self?.retryAttempt = 0
            self?.connect()
        }
    }
    
    // MARK: 事件处理
    func addListener(for event: String, handler: @escaping (Any) -> Void) {
        if eventListeners[event] == nil {
            eventListeners[event] = []
        }
        eventListeners[event]?.append(handler)
        
        // 如果已连接，立即注册事件
        socket?.on(event) { [weak self] data, _ in
            self?.handleEvent(event, data: data)
        }
    }
    
    private func handleEvent(_ event: String, data: [Any]) {
        guard let handlers = eventListeners[event] else { return }
        
        let payload = data.first ?? data
        handlers.forEach { $0(payload) }
    }
    
    func emit(_ event: String, _ items: SocketData...) {
        if isConnected {
            socket?.emit(event, with: items)
        }else{
            log("Socket 未连接 - ...")
        }
        
    }
}

extension SocketConnectionManager {
    //开启心跳包
    private func startHeartTimer() {
        //开启定时器 不断接收服务器发来的消息
        self.timer.start(timeInterval: pingInterval, repeats: true, handle: {
            DispatchQueue.main.async {
                if self.socket?.status == .connected {
                    // 发送消息
                    self.socket?.emit("chatMessage", "Hello from Swift client") {}
                }
            }
        })
    }
    
    //关闭心跳包
    private func cancelHeartTimer() {
        self.timer.cancel()
    }
    
    // 动态心跳间隔（Wi-Fi 3s/蜂窝5s）
    private var pingInterval: TimeInterval {
        monitor.currentPath.isExpensive ? 5 : 3
    }
}

@objc private  extension SocketConnectionManager {
    // MARK: 生命周期管理
    func appDidEnterBackground() {
        socket?.disconnect()
    }
    
    func appWillEnterForeground() {
        connect()
    }
}



